use std::fmt::Display;

fn calc(start: &str, date: Date, retire_age_start: f64) -> (Date, f64, i32) {
    let start_date = Date::from(start);
    let months = date.months_to_other(&start_date) / 4 + 1;
    let mut year = months / 12;
    let month = months % 12;
    let retire_age = retire_age_start + year as f64 + month as f64 / 12.0;
    if date.month + month > 12 {
        year += 1;
    }
    let retire_date = Date {
        year: date.year + retire_age_start as i32 + year,
        month: if date.month + month > 12 {
            date.month + month - 12
        } else {
            date.month + month
        },
    };
    (retire_date, retire_age, month)
}

pub fn retire_time(time: &str, tp: &str) -> String {
    match tp {
        "男职工" => {
            let date = Date::from(time);
            if date.year >= 1977 {
                let retire_date = Date {
                    year: date.year + 63,
                    month: date.month,
                };
                format!("{},63,36", retire_date)
            } else if date.year < 1965 {
                let retire_date = Date {
                    year: date.year + 60,
                    month: date.month,
                };
                format!("{},60,0", retire_date)
            } else {
                let (retire_date, retire_age, month) = calc("1965-01", date, 60.0);
                format!("{},{:.2},{}", retire_date, retire_age, month)
            }
        }
        "原法定退休年龄55周岁女职工" => {
            let date = Date::from(time);
            if date.year >= 1982 {
                let retire_date = Date {
                    year: date.year + 58,
                    month: date.month,
                };
                format!("{},58,36", retire_date)
            } else if date.year < 1965 {
                let retire_date = Date {
                    year: date.year + 55,
                    month: date.month,
                };
                format!("{},55,0", retire_date)
            } else {
                let (retire_date, retire_age, month) = calc("1970-01", date, 55.0);
                format!("{},{:.2},{}", retire_date, retire_age, month)
            }
        }
        "原法定退休年龄50周岁女职工" => {
            let date = Date::from(time);
            if date.year >= 1985 {
                let retire_date = Date {
                    year: date.year + 55,
                    month: date.month,
                };
                format!("{},55,60", retire_date)
            } else if date.year < 1975 {
                let retire_date = Date {
                    year: date.year + 50,
                    month: date.month,
                };
                format!("{},50,0", retire_date)
            } else {
                let (retire_date, retire_age, month) = calc("1975-01", date, 50.0);
                format!("{},{:.2},{}", retire_date, retire_age, month)
            }
        }
        _ => "".to_string(),
    }
}

struct Date {
    year: i32,
    month: i32,
}

impl Date {
    fn months_to_other(&self, other: &Date) -> i32 {
        let mut months = (self.year - other.year) * 12;
        months += self.month - other.month;
        months
    }
}

impl Display for Date {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.month < 10 {
            write!(f, "{}-0{}", self.year, self.month)
        } else {
            write!(f, "{}-{}", self.year, self.month)
        }
    }
}

impl From<&str> for Date {
    fn from(value: &str) -> Self {
        let s: Vec<&str> = value.split("-").collect();
        Self {
            year: s[0].parse().unwrap(),
            month: s[1].parse().unwrap(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Date;

    #[test]
    fn test_months_to_other() {
        let date = Date {
            year: 1965,
            month: 4,
        };
        let other = Date {
            year: 1965,
            month: 1,
        };
        dbg!(date.months_to_other(&other));
    }
}
